package com.so206.crond.process;

import com.so206.PaySystemApplication;
import com.so206.interceptr.BaseInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.security.util.SignatureFileVerifier;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * 验证包签名
 */
public class VerfySign implements Runnable {

    private static final Logger logger = LoggerFactory.getLogger(PaySystemApplication.class);

    /**
     * 调试时 设置为 false 跳过 签名验证
     * 发布时 设置为 true 检测 文件签名
     */
    private static final boolean isVerifyFileSign = false;

    /**
     * 当前系统版本
     */
    public final static String sys_version = "2020-12 Update Test";

    /**
     * 错误文件列表
     */
    public static ArrayList<Object> error_file = new ArrayList<>();

    /**
     * 验证 Jar 文件签名,检测文件是否被修改
     */
    @Override
    public void run() {
        String filePath = System.getProperty("java.class.path");
        try {
            if (isVerifyFileSign) {
                logger.info("开始验证文件:" + filePath);
                BaseInterceptor.verify = verifyJar(filePath);
                if (!BaseInterceptor.verify) {
                    for (Object o : error_file) {
                        System.out.println(o);
                    }
                }
                logger.info("文件:" + filePath + " 验证完成!");
            }
        } catch (Exception e) {
            BaseInterceptor.verify = false;
            error_file.add(e.getMessage());
        }
    }

    private boolean verifyJar(String jarName) {
        try (JarFile jf = new JarFile(jarName, true)) {
            Vector<JarEntry> entriesVec = new Vector<>();
            ArrayList<String> list = new ArrayList<>();
            byte[] buffer = new byte[8192];
            Enumeration<JarEntry> entries = jf.entries();
            while (entries.hasMoreElements()) {
                JarEntry je = entries.nextElement();
                entriesVec.addElement(je);
                try (InputStream is = jf.getInputStream(je)) {
                    String name = je.getName();
                    if (signatureRelated(name) && SignatureFileVerifier.isBlockOrSF(name)) {
                        list.add(name);
                    } else {
                        while (is.read(buffer, 0, buffer.length) != -1) {
                            continue;
                        }
                    }
                }
            }
            if (list.size() == 0) {
                error_file.add("程序未签名,请签名后重新启动!");
                return false;
            }
        } catch (Exception e) {
            error_file.add(e.getMessage());
            return false;
        }
        return true;
    }

    private boolean signatureRelated(String name) {
        return SignatureFileVerifier.isSigningRelated(name);
    }


}
